package com.example.learn_jfreechart.utils;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.DefaultCategoryDataset;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Random;

/**
 * @author : fantastic
 * @date : 2024/10/23 20:49
 * @desc : this class for xxxxx
 * https://blog.csdn.net/chehec2010/article/details/80988072
 * https://juejin.cn/post/7123001463810293791?searchId=20241023203734C23F2F066289F793E132#heading-3
 *
 **/
public class GenerateChartUtil {

    public static void main(String[] args) {
        LinkedHashMap<String,Long> map=new LinkedHashMap<>();
        for (int i = 0; i < 30; i++) {
            int i1 = new Random().nextInt(200) - 100;
            map.put("202410"+i, (long) i1);
        }
        JFreeChart jFreeChart = generateChartUtil(null, map);
        exportChartAsImage(jFreeChart,"output.png",map.size()*150,2000);
    }


    public static JFreeChart generateChartUtil(String title, LinkedHashMap<String,Long> chatDataMap){
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        chatDataMap.forEach((key, value) -> dataset.addValue(value, "日期", key));

        JFreeChart barChart = ChartFactory.createBarChart(
                // 图表标题
                title,
                // 横坐标标签
                null,
                // 纵坐标标签
                "金额",
                // 数据集
                dataset,
                // 柱状图方向
                PlotOrientation.VERTICAL,
                // 是否包含图例
                true,
                // 是否生成工具提示
                true,
                // 是否生成URL链接
                false
        );

        // 获取绘图区并设置自定义的柱状图渲染器
        CategoryPlot categoryPlot = barChart.getCategoryPlot();


        BarRenderer barRenderer = new BarRenderer() {
            @Override
            public Paint getItemPaint(int row, int column) {
                double value = dataset.getValue(row, column).doubleValue();
                if (value < 0) {
                    return Color.RED;
                } else {
                    return Color.BLUE;
                }
            }
        };

        // 去除柱子的阴影和轮廓线
        barRenderer.setDrawBarOutline(false); // 去除柱子的轮廓线
        barRenderer.setShadowVisible(false); // 去除柱子的阴影

        barRenderer.setItemMargin(0.25);
        barRenderer.setMaximumBarWidth(0.5);
        // 设置高光颜色为透明，去除高光效果
        // 设置半透明蓝色
//        barRenderer.setSeriesPaint(0, new Color(0, 0, 255, 150));
        // 设置横坐标和纵坐标的字体大小
        Font labelFont = new Font("SansSerif", Font.PLAIN, 25);
        // 设置字体大小为18
        Font axisTitleFont = new Font("SansSerif", Font.BOLD, 30);
        // 设置轴标题字体大小为20

        // 设置横坐标轴
        CategoryAxis domainAxis = categoryPlot.getDomainAxis();
        domainAxis.setVisible(true);
        domainAxis.setLabelFont(axisTitleFont);
        domainAxis.setTickLabelFont(labelFont);
        double angle = Math.toRadians(40); // 将角度转换为弧度
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.createDownRotationLabelPositions(angle));        // 设置纵坐标轴


        NumberAxis rangeAxis = (NumberAxis) categoryPlot.getRangeAxis();
        rangeAxis.setLabelFont(axisTitleFont);
        rangeAxis.setTickLabelFont(labelFont);


        categoryPlot.setRenderer(barRenderer);
        categoryPlot.setBackgroundPaint(Color.WHITE);

        categoryPlot.setRangeZeroBaselineVisible(true);

        // 移除绘图区域的边框
        categoryPlot.setOutlineVisible(false);

        // 自动调整纵坐标轴的刻度标记
        adjustRangeAxisTicks((NumberAxis) categoryPlot.getRangeAxis(), dataset);
//        if (dataset.getRowCount()>=15){
//            int interval = 5;
//            for (int i = 0; i < dataset.getRowCount(); i++) {
//                for (int j = 0; j < dataset.getColumnCount(); j++) {
//                    if ((j + 1) % interval != 0) {
//                        barRenderer.setItemLabelGenerator(i, j, null); // 隐藏标签
//                    } else {
//                        barRenderer.setItemLabelGenerator(i, j, new StandardCategoryItemLabelGenerator()); // 显示标签
//                    }
//                }
//            }
//        }
        return barChart;
    }

    /**
     * 动态调整纵坐标轴的刻度标记。
     *
     * @param rangeAxis 纵坐标轴
     * @param dataset 数据集
     */
    private static void adjustRangeAxisTicks(NumberAxis rangeAxis, DefaultCategoryDataset dataset) {
        double min = Double.MAX_VALUE;
        double max = Double.MIN_VALUE;

        // 计算数据集中的最大值和最小值
        for (int i = 0; i < dataset.getRowCount(); i++) {
            for (int j = 0; j < dataset.getColumnCount(); j++) {
                double value = dataset.getValue(i, j).doubleValue();
                if (value < min) {
                    min = value;
                }
                if (value > max) {
                    max = value;
                }
            }
        }

        // 设置轴的范围
        rangeAxis.setRange(min, max);

        // 计算合适的刻度间隔
        double tickInterval = calculateTickInterval(min, max);

        // 设置刻度单位
        rangeAxis.setTickUnit(new NumberTickUnit(tickInterval));
    }

    /**
     * 根据数据范围计算合适的刻度间隔。
     *
     * @param minValue 最小值
     * @param maxValue 最大值
     * @return 刻度间隔
     */
    private static double calculateTickInterval(double minValue, double maxValue) {
        double range = maxValue - minValue;
        // 默认每5个单位一个刻度
        double interval = range / 5;

        // 确保刻度间隔合理
        if (interval < 1) {
            interval = 1;
        } else if (interval > 100) {
            interval = 100;
        } else {
            // 使刻度间隔为整数
            interval = Math.ceil(interval / 10) * 10;
        }

        return interval;
    }

    /**
     * 导出图表为图片文件
     *
     * @param chart JFreeChart实例
     * @param filename 文件名
     * @param width 图片宽度
     * @param height 图片高度
     */
    public static void exportChartAsImage(JFreeChart chart, String filename, int width, int height) {
        try {
            ChartUtilities.saveChartAsPNG(new File(filename), chart, width, height);
        } catch (IOException e) {
            System.err.println("Error saving the chart as image: " + e.getMessage());
        }
    }
}
